package linear

import (
	"bytes"
	"errors"
	"fmt"
	"strconv"
)

// 感性活动存在论， 感性实践的唯物主义

var (
	ErrIndexOutOfRange = errors.New("index out of range")
)

// Node
// => 这里为了练习， 添加了 index 相关的链表操作
type Node struct {
	value int
	next  *Node
}

func New(value int, next *Node) *Node {
	return &Node{value, next}
}

func (n *Node) AddFirst(value int) error { return n.Add(0, value) }
func (n *Node) AddLast(value int) error  { return n.Add(n.Size(), value) }

// Add 链表尾添加
func (n *Node) Add(index, value int) error {
	if n == nil {
		fmt.Println("Add value to nil Node.")
		return nil
	}

	if index < 0 || index > n.Size() {
		return ErrIndexOutOfRange
	}

	cur := n
	for cur.next != nil {
		cur = cur.next
	}
	cur.next = &Node{value, nil}
	return nil
}

func (n *Node) GetFirst() (int, error) { return n.Get(0) }
func (n *Node) GetLast() (int, error)  { return n.Get(n.Size() - 1) }

// Get 查询
func (n *Node) Get(index int) (int, error) {
	if n == nil {
		return -1, errors.New("nil node")
	}
	if index < 0 || index >= n.Size() {
		return -1, ErrIndexOutOfRange
	}

	cur := n
	for i := 0; i < index; i++ {
		cur = cur.next
	}
	return cur.value, nil
}

// Set 修改
func (n *Node) Set(index int, value int) (int, error) {
	if n == nil {
		return -1, errors.New("nil node")
	}

	if index < 0 || index >= n.Size() {
		return -1, ErrIndexOutOfRange
	}

	cur := n
	for i := 0; i < index; i++ {
		cur = cur.next
	}

	oldVal := cur.value
	cur.value = value
	return oldVal, nil
}

func (n *Node) RemoveFirst() (int, error) { return n.Remove(0) }
func (n *Node) RemoveLast() (int, error)  { return n.Remove(n.Size() - 1) }

// Remove 删除指定位置元素
func (n *Node) Remove(index int) (int, error) {
	if n == nil {
		return -1, errors.New("nil node")
	}

	if index < 0 || index >= n.Size() {
		return -1, ErrIndexOutOfRange
	}

	prev := New(-1, n)
	for i := 0; i < index; i++ {
		prev = prev.next
	}
	oldNode := prev.next
	oldNode.next = nil
	return oldNode.value, nil
}

// RemoveElem 删除指定值的元素
func (n *Node) RemoveElem(value int) error {
	if n == nil {
		return errors.New("nil node")
	}
	// TODO 移除所有指定值的元素
	return nil
}

func removeElems(node *Node, value int) *Node {
	if node == nil {
		return nil
	}
	node.next = removeElems(node.next, value)
	if node.value == value {
		return node.next
	} else {
		return node
	}
}

// Contains 判断
func (n *Node) Contains(value int) bool {
	if n == nil { // nil node
		fmt.Println("current Node is nil")
		return false
	}

	cur := n
	for cur != nil {
		if cur.value == value {
			return true
		}
		cur = cur.next
	}
	return false
}

// String 输出
func (n *Node) String() string {
	cur, buf := n, bytes.NewBufferString("")
	for cur != nil {
		buf.WriteString(strconv.Itoa(cur.value))
		buf.WriteString("->")
		cur = cur.next
	}
	buf.WriteString("nil")
	return buf.String()
}

// Size 计算一下个数
func (n *Node) Size() int {
	if n == nil {
		return 0
	}
	c, cur := 0, n
	for cur != nil {
		c++
		cur = cur.next
	}
	return c
}
